from __future__ import annotations

import logging
from pathlib import Path
from typing import Optional

import pandas as pd

logger = logging.getLogger("excel.utils")


def load_excel_safely(file_path: str, sheet_name: Optional[str] = None) -> pd.DataFrame:
    """
    安全、通用的 Excel/CSV 读取函数：
    - 支持多 sheet，默认取第一个或指定的 sheet
    - 使用 keep_default_na=False 避免把空字符串变成 NaN
    - 统一转成字符串以最大化保留可见内容
    """
    path = Path(file_path)
    try:
        ext = path.suffix.lower()
        if ext in {".csv"}:
            df = pd.read_csv(
                path,
                dtype=str,
                keep_default_na=False,
            )
        else:
            try:
                df = pd.read_excel(
                    path,
                    sheet_name=sheet_name,
                    dtype=str,
                    keep_default_na=False,
                    engine="openpyxl",
                )
            except Exception:
                # openpyxl 不支持老式 .xls 时回退默认引擎
                df = pd.read_excel(
                    path,
                    sheet_name=sheet_name,
                    dtype=str,
                    keep_default_na=False,
                )

        if isinstance(df, dict):
            df = df[sheet_name] if sheet_name and sheet_name in df else list(df.values())[0]

        df = df.fillna("").astype(str)
        df.columns = [
            str(col) if (col is not None and str(col).strip() != "") else f"col_{i}"
            for i, col in enumerate(df.columns)
        ]
        return df
    except Exception as exc:
        logger.error("Excel 读取失败", exc_info=exc)
        raise Exception(f"Excel 读取失败: {exc}")


def dataframe_to_llm_markdown(df: pd.DataFrame, max_rows: int = 50) -> str:
    """
    将 DataFrame 转为适合 LLM 的 Markdown 表格字符串。
    默认只取前 max_rows 行，防止 prompt 过长。
    """
    preview = df.head(max_rows).copy()
    try:
        markdown = preview.to_markdown(index=False)
    except Exception as exc:
        logger.warning("DataFrame to_markdown 失败，回退 to_string", exc_info=exc)
        markdown = preview.to_string(index=False)
    total_rows = len(df)
    if total_rows > max_rows:
        markdown = f"仅展示前 {max_rows} 行 / 共 {total_rows} 行：\n" + markdown
    return markdown
